package com.partsoft.utils;

public abstract class HexUtils {
	
	private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	public static boolean isHex(int value) {
		if ((value >= 65) && (value <= 70)) {
			return true;
		}
		if ((value >= 97) && (value <= 102)) {
			return true;
		}
		return NumericUtils.isNumberValue(value);
	}

	public static boolean isHex(String value) {
		for (int i = 0; i < value.length(); i++) {
			if (!isHex(value.charAt(i)))
				return false;
		}
		return true;
	}

	public static String toHex(byte value) {
		StringBuffer buffer = new StringBuffer(2);
		buffer.append(HEX_CHARS[(value >> 4 & 0xF)]);
		buffer.append(HEX_CHARS[(value & 0xF)]);
		return buffer.toString();
	}

	public static String toHex(short value) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < 4; i++) {
			buffer.append(HEX_CHARS[(value >> 4 * (4 - i - 1) & 0xF)]);
		}
		return buffer.toString();
	}

	public static String toHex(int value) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < 8; i++) {
			buffer.append(HEX_CHARS[(value >> 4 * (8 - i - 1) & 0xF)]);
		}
		return buffer.toString();
	}

	public static String toHex(long value) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < 16; i++) {
			buffer.append(HEX_CHARS[(int) (value >> 4 * (16 - i - 1) & 0xF)]);
		}
		return buffer.toString();
	}

	public static String toHex(byte[] bytes) {
		return toHex(bytes, 0, bytes != null ? bytes.length : 0);
	}

	public static String toHex(byte[] bytes, int length) {
		return toHex(bytes, 0, length);
	}

	public static String toHex(byte[] bytes, int offset, int length) {
		int size = bytes != null ? bytes.length : 0;
		if (size < length)
			length = size;
		StringBuffer buffer = new StringBuffer(length << 1);
		for (int i = offset; i < offset + length; i++) {
			buffer.append(HEX_CHARS[(bytes[i] >> 4 & 0xF)]);
			buffer.append(HEX_CHARS[(bytes[i] & 0xF)]);
		}
		return buffer.toString();
	}

	public static int fromHex(char hex) {
		if ((hex >= 'A') && (hex <= 'F')) {
			return hex - 'A' + 10;
		}
		if ((hex >= 'a') && (hex <= 'f')) {
			return hex - 'a' + 10;
		}
		return NumericUtils.fromNumber(hex);
	}

	public static byte byteFromHex(String hexes) {
		byte value = 0;
		if ((hexes != null) && (hexes.startsWith("0x") || hexes.startsWith("0X"))) {
			hexes = hexes.substring(2);
		}
		for (int i = 0; (hexes != null) && (i < hexes.length()); i++) {
			value = (byte) (value << 4);
			value = (byte) (value | (byte) (fromHex(hexes.charAt(i)) & 0xF));
		}

		return value;
	}

	public static short shortFromHex(String hexes) {
		short value = 0;
		if ((hexes != null) && (hexes.startsWith("0x") || hexes.startsWith("0X"))) {
			hexes = hexes.substring(2);
		}
		for (int i = 0; (hexes != null) && (i < hexes.length()); i++) {
			value = (short) (value << 4);
			value = (short) (value | (short) (fromHex(hexes.charAt(i)) & 0xF));
		}
		return value;
	}

	public static int intFromHex(String hexes) {
		int value = 0;
		if ((hexes != null) && (hexes.startsWith("0x") || hexes.startsWith("0X"))) {
			hexes = hexes.substring(2);
		}

		for (int i = 0; (hexes != null) && (i < hexes.length()); i++) {
			value <<= 4;
			value |= fromHex(hexes.charAt(i)) & 0xF;
		}

		return value;
	}

	public static long longFromHex(String hexes) {
		long value = 0L;

		if ((hexes != null) && (hexes.startsWith("0x") || hexes.startsWith("0X"))) {
			hexes = hexes.substring(2);
		}
		for (int i = 0; (hexes != null) && (i < hexes.length()); i++) {
			value <<= 4;
			value |= fromHex(hexes.charAt(i)) & 0xF;
		}
		return value;
	}

	public static byte[] bytesFromHex(String hexes) {
		if ((hexes != null) && (hexes.startsWith("0x"))) {
			hexes = hexes.substring(2);
		}

		int length = (hexes == null ? 0 : hexes.length()) + 1 >> 1;
		byte[] bytes = new byte[length];
		for (int i = 0; i < 2 * length; i++) {
			byte value = 0;
			if (i < hexes.length())
				value = (byte) fromHex(hexes.charAt(i));
			int tmp_value = (i >> 1);
			bytes[tmp_value] = (byte) (bytes[tmp_value] | value << ((i & 0x01) == 0x01 ? 0 : 4));
		}
		return bytes;
	}
}